package v1

import (
	"errors"
	"fmt"
	"strconv"
	"wms/internal/model/request"
	"wms/internal/service"
	"wms/pkg/common"
	"wms/pkg/logger"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

// InventoryController 库存控制器
type InventoryController struct {
	inventoryService *service.InventoryService
}

// NewInventoryController 创建库存控制器
func NewInventoryController(db *gorm.DB, logger *zap.Logger) *InventoryController {
	return &InventoryController{
		inventoryService: service.NewInventoryService(db, logger),
	}
}

// ListInventory godoc
// @Summary 获取库存列表
// @Description 获取库存列表，支持分页和搜索
// @Tags 库存管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param keyword query string false "搜索关键词"
// @Success 200 {object} resp.Response{data=[]model.Inventory} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory [get]
func (c *InventoryController) ListInventory(ctx *gin.Context) {
	var req request.InventoryListRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定库存列表请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	list, total, err := c.inventoryService.ListInventory(&req)
	if err != nil {
		logger.Error("获取库存列表失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, gin.H{
		"list":  list,
		"total": total,
		"page":  req.Page,
		"size":  req.PageSize,
	})
}

// GetInventory godoc
// @Summary 获取库存详情
// @Description 获取指定库存的详细信息
// @Tags 库存管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "库存ID"
// @Success 200 {object} resp.Response{data=model.Inventory} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/{id} [get]
func (c *InventoryController) GetInventory(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析库存ID失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	inventory, err := c.inventoryService.GetInventory(uint(id))
	if err != nil {
		logger.Error("获取库存详情失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, inventory)
}

// AdjustInventory godoc
// @Summary 调整库存
// @Description 调整商品库存数量
// @Tags 库存管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body request.InventoryAdjustRequest true "调整信息"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/adjust [post]
func (c *InventoryController) AdjustInventory(ctx *gin.Context) {
	var req request.InventoryAdjustRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定库存调整请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 获取操作人ID
	userID := common.GetUserID(ctx)

	if err := c.inventoryService.AdjustInventory(&req, userID); err != nil {
		logger.Error("调整库存失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, "调整库存成功")
}

// GetInventoryAlerts godoc
// @Summary 获取库存预警列表
// @Description 获取库存预警列表，支持分页和筛选
// @Tags 库存管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Success 200 {object} resp.Response{data=[]model.InventoryAlert} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/alerts [get]
func (c *InventoryController) GetInventoryAlerts(ctx *gin.Context) {
	var req request.ListInventoryAlertRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定库存预警列表请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	alerts, total, err := c.inventoryService.GetInventoryAlerts(&req)
	if err != nil {
		logger.Error("获取库存预警列表失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, gin.H{
		"list":  alerts,
		"total": total,
		"page":  req.Page,
		"size":  req.PageSize,
	})
}

// GetInventoryAlertCount godoc
// @Summary 获取库存预警数量
// @Description 获取当前库存预警的总数量
// @Tags 库存管理
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} resp.Response{data=int} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/alerts/count [get]
func (c *InventoryController) GetInventoryAlertCount(ctx *gin.Context) {
	count, err := c.inventoryService.GetInventoryAlertCount()
	if err != nil {
		logger.Error("获取库存预警数量失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, count)
}

// CreateInbound godoc
// @Summary 创建入库单
// @Description 创建新的入库单
// @Tags 入库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body request.InboundCreateRequest true "入库单信息"
// @Success 200 {object} resp.Response{data=model.Inbound} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/inbound [post]
func (c *InventoryController) CreateInbound(ctx *gin.Context) {
	var req request.InboundCreateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定创建入库单请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 获取操作人ID
	userID := common.GetUserID(ctx)

	inbound, err := c.inventoryService.CreateInbound(&req, userID)
	if err != nil {
		logger.Error("创建入库单失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, inbound)
}

// UpdateInbound godoc
// @Summary 更新入库单
// @Description 更新入库单信息
// @Tags 入库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "入库单ID"
// @Param request body request.InboundUpdateRequest true "入库单信息"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/inbound/{id} [put]
func (c *InventoryController) UpdateInbound(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析入库单ID失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	var req request.InboundUpdateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定更新入库单请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 获取操作人ID
	userID := common.GetUserID(ctx)

	if err := c.inventoryService.UpdateInbound(uint(id), &req, userID); err != nil {
		logger.Error("更新入库单失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, "更新入库单成功")
}

// GetInbound godoc
// @Summary 获取入库单详情
// @Description 获取指定入库单的详细信息
// @Tags 入库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "入库单ID"
// @Success 200 {object} resp.Response{data=response.InboundOrderDetailResponse} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/inbound/{id} [get]
func (c *InventoryController) GetInbound(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析入库单ID失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 调用修改后的 Service 方法，获取 DTO
	inboundDetailResp, err := c.inventoryService.GetInboundByID(uint(id))
	if err != nil {
		logger.Error("获取入库单详情失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 将 DTO 传递给 Success
	common.Success(ctx, inboundDetailResp)
}

// ListInbound godoc
// @Summary 获取入库单列表
// @Description 获取入库单列表，支持分页和搜索
// @Tags 入库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param keyword query string false "搜索关键词"
// @Success 200 {object} resp.Response{data=[]model.Inbound} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/inbound [get]
func (c *InventoryController) ListInbound(ctx *gin.Context) {
	var req request.InboundListRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定入库单列表请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	list, total, err := c.inventoryService.ListInbound(&req)
	if err != nil {
		logger.Error("获取入库单列表失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, gin.H{
		"list":  list,
		"total": total,
		"page":  req.Page,
		"size":  req.PageSize,
	})
}

// CreateOutbound godoc
// @Summary 创建出库单
// @Description 创建新的出库单
// @Tags 出库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body request.OutboundCreateRequest true "出库单信息"
// @Success 200 {object} resp.Response{data=model.Outbound} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/outbound [post]
func (c *InventoryController) CreateOutbound(ctx *gin.Context) {
	var req request.OutboundCreateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定创建出库单请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 获取操作人ID
	userID := common.GetUserID(ctx)

	outbound, err := c.inventoryService.CreateOutbound(&req, userID)
	if err != nil {
		logger.Error("创建出库单失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, outbound)
}

// UpdateOutbound godoc
// @Summary 更新出库单
// @Description 更新出库单信息
// @Tags 出库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "出库单ID"
// @Param request body request.OutboundUpdateRequest true "出库单信息"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/outbound/{id} [put]
func (c *InventoryController) UpdateOutbound(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析出库单ID失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	var req request.OutboundUpdateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定更新出库单请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 获取操作人ID
	userID := common.GetUserID(ctx)

	if err := c.inventoryService.UpdateOutbound(uint(id), &req, userID); err != nil {
		logger.Error("更新出库单失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, "更新出库单成功")
}

// GetOutbound godoc
// @Summary 获取出库单详情
// @Description 获取指定出库单的详细信息
// @Tags 出库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "出库单ID"
// @Success 200 {object} resp.Response{data=model.Outbound} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/outbound/{id} [get]
func (c *InventoryController) GetOutbound(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析出库单ID失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	outbound, err := c.inventoryService.GetOutboundByID(uint(id))
	if err != nil {
		logger.Error("获取出库单详情失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, outbound)
}

// ListOutbound godoc
// @Summary 获取出库单列表
// @Description 获取出库单列表，支持分页和搜索
// @Tags 出库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param keyword query string false "搜索关键词"
// @Success 200 {object} resp.Response{data=[]response.OutboundOrderListResponse} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/outbound [get]
func (c *InventoryController) ListOutbound(ctx *gin.Context) {
	var req request.OutboundListRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定出库单列表请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	list, total, err := c.inventoryService.ListOutbound(&req)
	if err != nil {
		logger.Error("获取出库单列表失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, gin.H{
		"list":  list,
		"total": total,
		"page":  req.Page,
		"size":  req.PageSize,
	})
}

// CreateInventoryCheck godoc
// @Summary 创建盘点单
// @Description 创建新的盘点单
// @Tags 盘点管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body request.InventoryCheckCreateRequest true "盘点单信息"
// @Success 200 {object} resp.Response{data=model.InventoryCheck} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/check [post]
func (c *InventoryController) CreateInventoryCheck(ctx *gin.Context) {
	var req request.InventoryCheckCreateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定创建库存盘点单请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 获取操作人ID
	userID := common.GetUserID(ctx)

	check, err := c.inventoryService.CreateInventoryCheck(&req, userID)
	if err != nil {
		logger.Error("创建库存盘点单失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, check)
}

// GetInventoryCheck godoc
// @Summary 获取盘点单详情
// @Description 获取指定盘点单的详细信息
// @Tags 盘点管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "盘点单ID"
// @Success 200 {object} resp.Response{data=model.InventoryCheck} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/check/{id} [get]
func (c *InventoryController) GetInventoryCheck(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析库存盘点单ID失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	check, err := c.inventoryService.GetInventoryCheckByID(uint(id))
	if err != nil {
		logger.Error("获取库存盘点单详情失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, check)
}

// ListInventoryCheck godoc
// @Summary 获取盘点单列表
// @Description 获取盘点单列表，支持分页和搜索
// @Tags 盘点管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param keyword query string false "搜索关键词"
// @Success 200 {object} resp.Response{data=[]model.InventoryCheck} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/check [get]
func (c *InventoryController) ListInventoryCheck(ctx *gin.Context) {
	var req request.InventoryCheckListRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定库存盘点单列表请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	list, total, err := c.inventoryService.ListInventoryCheck(&req)
	if err != nil {
		logger.Error("获取库存盘点单列表失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, gin.H{
		"list":  list,
		"total": total,
		"page":  req.Page,
		"size":  req.PageSize,
	})
}

// CompleteInventoryCheck godoc
// @Summary 完成盘点
// @Description 完成指定盘点单
// @Tags 盘点管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "盘点单ID"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/check/{id}/complete [post]
func (c *InventoryController) CompleteInventoryCheck(ctx *gin.Context) {
	// Parse ID from path parameter to uint
	idStr := ctx.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		logger.Warn("解析盘点单ID失败", zap.String("id", idStr), zap.Error(err))
		// Use common.Error with a standard error
		common.Error(ctx, errors.New("无效的盘点单ID"))
		return
	}

	var req request.CompleteInventoryCheckRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定完成盘点请求参数失败", zap.Error(err))
		common.Error(ctx, err) // common.Error handles response
		return
	}

	// Get operator UserID from context
	userID := common.GetUserID(ctx)

	// Call service with uint ID and userID
	// IMPORTANT: Assumes service signature is CompleteInventoryCheck(uint, *request.CompleteInventoryCheckRequest, uint)
	if err := c.inventoryService.CompleteInventoryCheck(uint(id), &req, userID); err != nil {
		logger.Error("完成盘点失败", zap.Uint("id", uint(id)), zap.Error(err))
		common.Error(ctx, err) // common.Error handles response
		return
	}

	common.Success(ctx, "盘点完成") // common.Success handles response
}

// GetInventoryHistory godoc
// @Summary 获取库存历史记录
// @Description 获取指定商品的库存变动历史记录
// @Tags 库存管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param product_id query uint true "商品ID"
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Success 200 {object} resp.Response{data=[]model.InventoryHistory} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/history [get]
func (c *InventoryController) GetInventoryHistory(ctx *gin.Context) {
	var req request.InventoryHistoryRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定库存历史记录请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	history, total, err := c.inventoryService.GetInventoryHistory(&req)
	if err != nil {
		logger.Error("获取库存历史记录失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, gin.H{
		"list":  history,
		"total": total,
		"page":  req.Page,
		"size":  req.PageSize,
	})
}

// GetInventoryStatus godoc
// @Summary 获取库存状态
// @Description 获取指定商品的当前库存状态
// @Tags 库存管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param cargo_id query uint true "货物ID"
// @Success 200 {object} resp.Response{data=model.InventoryStatus} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/status [get]
func (c *InventoryController) GetInventoryStatus(ctx *gin.Context) {
	var req request.InventoryStatusRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定库存状态请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	status, err := c.inventoryService.GetInventoryStatus(req.CargoID)
	if err != nil {
		logger.Error("获取库存状态失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, status)
}

// SetInventoryAlert godoc
// @Summary 设置库存预警
// @Description 设置商品的库存预警阈值
// @Tags 库存管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body request.InventoryAlertRequest true "预警设置"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/alert [post]
func (c *InventoryController) SetInventoryAlert(ctx *gin.Context) {
	var req request.InventoryAlertRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定库存预警设置请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	if err := c.inventoryService.SetInventoryAlert(&req); err != nil {
		logger.Error("设置库存预警失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, "设置库存预警成功")
}

// ReceiveInbound godoc
// @Summary 执行收货操作
// @Description 对"待收货"状态的入库单执行收货，记录实收数量等信息
// @Tags 入库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "入库单ID"
// @Param request body request.ReceiveRequest true "收货信息"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inbound/orders/{id}/receive [post]
func (c *InventoryController) ReceiveInbound(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析入库单ID失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	var req request.ReceiveRequest // 假设已在 request 包中定义
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定收货请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	userID := common.GetUserID(ctx)

	// 从请求中获取preserveStatus标志，如果为true则不自动更新入库单状态
	preserveStatus := req.PreserveStatus
	logger.Info("收货操作", zap.Bool("preserveStatus", preserveStatus))

	if err := c.inventoryService.ReceiveOrder(uint(id), &req, userID); err != nil {
		logger.Error("执行收货操作失败", zap.Uint("orderID", uint(id)), zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, "收货操作成功")
}

// PutawayInbound godoc
// @Summary 执行上架操作
// @Description 对"待上架"状态的入库单执行上架，更新库存
// @Tags 入库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "入库单ID"
// @Param request body request.PutawayRequest true "上架信息"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inbound/orders/{id}/putaway [post]
func (c *InventoryController) PutawayInbound(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析入库单ID失败", zap.Error(err))
		common.Error(ctx, errors.New("入库单ID无效"))
		return
	}

	var req request.PutawayRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定上架请求参数失败", zap.Error(err))
		common.Error(ctx, fmt.Errorf("无效的请求格式: %w", err))
		return
	}

	userID := common.GetUserID(ctx)

	if err := c.inventoryService.PutawayOrder(uint(id), &req, userID); err != nil {
		logger.Error("执行上架操作失败", zap.Error(err))
		common.ErrorWithMsg(ctx, err, fmt.Sprintf("上架失败: %s", err.Error()))
		return
	}

	common.Success(ctx, "上架成功")
}

// PickOutbound godoc
// @Summary 执行拣货操作
// @Description 对"待拣货"状态的出库单执行拣货
// @Tags 出库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "出库单ID"
// @Param request body request.PickRequest true "拣货信息"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /outbound/orders/{id}/pick [post]
func (c *InventoryController) PickOutbound(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析出库单ID失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	var req request.PickRequest // 假设已在 request 包中定义
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定拣货请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	userID := common.GetUserID(ctx)

	if err := c.inventoryService.PickOrder(uint(id), &req, userID); err != nil {
		logger.Error("执行拣货操作失败", zap.Uint("orderID", uint(id)), zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, "拣货操作成功")
}

// ShipOutbound godoc
// @Summary 执行发货操作
// @Description 对"待发货"状态的出库单执行发货，扣减库存
// @Tags 出库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "出库单ID"
// @Param request body request.ShipRequest true "发货信息 (可能包含物流单号等)"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /outbound/orders/{id}/ship [post]
func (c *InventoryController) ShipOutbound(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析出库单ID失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	var req request.ShipRequest // 假设已在 request 包中定义
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定发货请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	userID := common.GetUserID(ctx)

	if err := c.inventoryService.ShipOrder(uint(id), &req, userID); err != nil {
		logger.Error("执行发货操作失败", zap.Uint("orderID", uint(id)), zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, "发货操作成功")
}

// CancelInbound godoc
// @Summary 取消入库单
// @Description 取消指定ID的入库单
// @Tags 入库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "入库单ID"
// @Param request body request.CancelRequest true "取消原因"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 404 {object} resp.Response "资源不存在"
// @Failure 405 {object} resp.Response "状态不允许操作"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/inbound/{id}/cancel [post] // 使用 POST 或 DELETE
func (c *InventoryController) CancelInbound(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析入库单ID失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	var req request.CancelRequest // 使用通用取消请求结构体
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定取消请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	userID := common.GetUserID(ctx)

	if err := c.inventoryService.CancelInbound(uint(id), userID); err != nil {
		logger.Error("取消入库单失败", zap.Uint("orderID", uint(id)), zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, "入库单取消成功")
}

// UpdateInboundStatus godoc
// @Summary 更新入库单状态
// @Description 更新指定ID的入库单状态
// @Tags 入库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "入库单ID"
// @Param request body request.UpdateStatusRequest true "状态更新信息"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 404 {object} resp.Response "资源不存在"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/inbound/orders/{id}/status [put]
func (c *InventoryController) UpdateInboundStatus(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析入库单ID失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	var req request.UpdateStatusRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定状态更新请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	logger.Info("收到更新入库单状态请求",
		zap.Uint("orderID", uint(id)),
		zap.String("newStatus", req.Status))

	userID := common.GetUserID(ctx)

	if err := c.inventoryService.UpdateInboundStatus(uint(id), &req, userID); err != nil {
		logger.Error("更新入库单状态失败", zap.Uint("orderID", uint(id)), zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, "入库单状态更新成功")
}

// UpdateOutboundStatus godoc
// @Summary 更新出库单状态
// @Description 更新指定ID的出库单状态
// @Tags 出库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "出库单ID"
// @Param request body request.UpdateStatusRequest true "状态更新信息"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 404 {object} resp.Response "资源不存在"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/outbound/orders/{id}/status [put]
func (c *InventoryController) UpdateOutboundStatus(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析出库单ID失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	var req request.UpdateStatusRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定状态更新请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	logger.Info("收到更新出库单状态请求",
		zap.Uint("orderID", uint(id)),
		zap.String("newStatus", req.Status))

	userID := common.GetUserID(ctx)

	if err := c.inventoryService.UpdateOutboundStatus(uint(id), &req, userID); err != nil {
		logger.Error("更新出库单状态失败", zap.Uint("orderID", uint(id)), zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, "出库单状态更新成功")
}

// GetLocationInventory godoc
// @Summary 获取库位库存信息
// @Description 获取指定库位ID的库存信息列表
// @Tags 库存管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "库位ID"
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param cargo_name query string false "货物名称"
// @Param cargo_code query string false "货物编码"
// @Param sort_by query string false "排序字段" Enums(created_at, quantity, expiry_date)
// @Param sort_order query string false "排序方向" Enums(asc, desc)
// @Success 200 {object} resp.Response{data=[]model.Inventory} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 404 {object} resp.Response "库位不存在"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/locations/{id}/inventory [get]
func (c *InventoryController) GetLocationInventory(ctx *gin.Context) {
	// 解析库位ID
	locationID, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析库位ID失败",
			zap.Error(err),
			zap.String("id_param", ctx.Param("id")))
		common.Error(ctx, errors.New("无效的库位ID"))
		return
	}

	logger.Info("获取库位库存信息",
		zap.Uint64("locationID", locationID),
		zap.String("client_ip", ctx.ClientIP()))

	// 解析分页和过滤请求参数
	var req request.InventoryLocationRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定查询参数失败",
			zap.Error(err),
			zap.Any("query_params", ctx.Request.URL.Query()))
		common.Error(ctx, errors.New("无效的查询参数"))
		return
	}

	// 确保分页参数有效
	if req.Page <= 0 {
		req.Page = 1
	}
	if req.PageSize <= 0 {
		req.PageSize = 10
	}
	if req.PageSize > 100 {
		req.PageSize = 100 // 限制最大页面大小
	}

	logger.Info("查询参数",
		zap.Int("page", req.Page),
		zap.Int("pageSize", req.PageSize),
		zap.String("cargoName", req.CargoName),
		zap.String("cargoCode", req.CargoCode),
		zap.String("sortBy", req.SortBy),
		zap.String("sortOrder", req.SortOrder))

	// 调用服务获取库位库存信息
	inventories, total, err := c.inventoryService.GetLocationInventory(uint(locationID), &req)
	if err != nil {
		if err.Error() == "库位不存在" {
			logger.Warn("库位不存在", zap.Uint64("locationID", locationID))
			common.Error(ctx, errors.New("库位不存在"))
			return
		}

		logger.Error("获取库位库存信息失败",
			zap.Error(err),
			zap.Uint64("locationID", locationID))
		common.Error(ctx, errors.New("获取库位库存信息失败"))
		return
	}

	logger.Info("成功获取库位库存信息",
		zap.Int64("total", total),
		zap.Int("count", len(inventories)),
		zap.Uint64("locationID", locationID))

	common.Success(ctx, gin.H{
		"list":  inventories,
		"total": total,
		"page":  req.Page,
		"size":  req.PageSize,
	})
}

// GetPickingTasks godoc
// @Summary 获取待拣货任务列表
// @Description 获取所有待拣货状态的出库单
// @Tags 出库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} resp.Response{data=[]model.OutboundOrder} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/outbound/picking-tasks [get]
func (c *InventoryController) GetPickingTasks(ctx *gin.Context) {
	userID := common.GetUserID(ctx)
	logger.Info("获取待拣货任务列表", zap.Uint("userID", userID))

	tasks, err := c.inventoryService.GetPickingTasks()
	if err != nil {
		logger.Error("获取待拣货任务列表失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, tasks)
}

// GetShippingTasks godoc
// @Summary 获取待发货任务列表
// @Description 获取所有待发货状态的出库单
// @Tags 出库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} resp.Response{data=[]model.OutboundOrder} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/outbound/shipping-tasks [get]
func (c *InventoryController) GetShippingTasks(ctx *gin.Context) {
	userID := common.GetUserID(ctx)
	logger.Info("获取待发货任务列表", zap.Uint("userID", userID))

	tasks, err := c.inventoryService.GetShippingTasks()
	if err != nil {
		logger.Error("获取待发货任务列表失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, tasks)
}

// GetWarehouseProducts godoc
// @Summary 获取仓库中有库存的商品列表
// @Description 获取指定仓库中所有有库存的商品列表，包含可用库存信息
// @Tags 库存管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "仓库ID"
// @Param keyword query string false "商品关键字(编码/名称)"
// @Param category_id query int false "商品分类ID"
// @Param status query int false "商品状态"
// @Success 200 {object} resp.Response{data=[]response.ProductWithInventory} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 404 {object} resp.Response "仓库不存在"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/warehouse/{id}/products [get]
func (c *InventoryController) GetWarehouseProducts(ctx *gin.Context) {
	warehouseID, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析仓库ID失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	var req request.ProductListRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定查询参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	products, err := c.inventoryService.GetWarehouseProducts(uint(warehouseID), &req)
	if err != nil {
		logger.Error("获取仓库商品列表失败", zap.Error(err), zap.Uint("warehouseID", uint(warehouseID)))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, products)
}

// GetOutboundStatistics godoc
// @Summary 获取出库统计数据
// @Description 获取出库相关的统计数据（如待拣货、待发货数量）
// @Tags 出库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} resp.Response{data=map[string]int64} "成功，返回统计数据"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /inventory/outbound/statistics [get]
func (c *InventoryController) GetOutboundStatistics(ctx *gin.Context) {
	stats, err := c.inventoryService.GetOutboundStatistics()
	if err != nil {
		logger.Error("获取出库统计数据失败", zap.Error(err))
		common.Error(ctx, errors.New("获取统计数据失败")) // 返回通用错误信息给前端
		return
	}
	common.Success(ctx, stats)
}

// GetProductLocations 获取指定产品在各库位的库存信息
func (c *InventoryController) GetProductLocations(ctx *gin.Context) {
	idStr := ctx.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil {
		// Use common.Error with a standard error
		common.Error(ctx, errors.New("无效的产品ID"))
		return
	}

	locations, err := c.inventoryService.GetProductLocations(uint(id))
	if err != nil {
		logger.Error("获取产品库位库存失败", zap.Uint64("productId", id), zap.Error(err))
		// Use common.Error with the original or a new error
		common.Error(ctx, fmt.Errorf("获取产品库位库存失败: %w", err)) // Wrap the original error
		return
	}

	common.Success(ctx, locations)
}
